//
//  VideoCompressManager.swift
//  ltsp
//
//  Created by jyvyi_ios on 2022/7/20.
//

import Foundation

protocol VideoCompressManager_H{
    
    /// 快速压缩
    /// - Parameters:
    ///   - videoUrl: 视频路径
    ///   - complete: 完成回调
    static func videoQuickCompress(with videoUrl:URL,complete:@escaping ReturnValueBlock<String>)
    
//    /// 每一帧的压缩。编码错误，还不能使用
//    /// - Parameters:
//    ///   - videoUrl: 视频路径
//    ///   - fileType: 类型
//    static func compressVideo(with videoUrl:URL,fileType:AVFileType) throws
}

class VideoCompressManager : VideoCompressManager_H{
    
//    /// 每一帧的压缩。编码错误，还不能使用
//    /// - Parameters:
//    ///   - videoUrl: 视频路径
//    ///   - fileType: 类型
//    static func compressVideo(with videoUrl:URL,
//                              fileType:AVFileType = .mp4
//    )throws{
//
//        let outputUrl = URL.init(fileURLWithPath:self.buildFilePath())
//
//        let videoSettings = self.performanceVideoSettings()
//        let audioSettings = self.performanceAudioSettings()
//
//        let asset = AVAsset.init(url: videoUrl)
//        let reader = try AVAssetReader.init(asset: asset)
//        let writer = try AVAssetWriter.init(url: outputUrl, fileType: fileType)
//
//        guard let videoTrack = asset.tracks(withMediaType: .video).first ,let audioTrack = asset.tracks(withMediaType: .audio).first else {
//            return
//        }
//        // Video
//        let videoOutput = AVAssetReaderTrackOutput.init(track: videoTrack, outputSettings: self.configVideoOutput())
//        let videoInput = AVAssetWriterInput.init(mediaType: .video, outputSettings: videoSettings)
//
//        if reader.canAdd(videoOutput){
//            reader.add(videoOutput)
//        }
//        if writer.canAdd(videoInput){
//            writer.add(videoInput)
//        }
//
//        // Audio
//
//        let audioOutput = AVAssetReaderTrackOutput.init(track: audioTrack, outputSettings: self.configAudioOutput())
//        let audioInput = AVAssetWriterInput.init(mediaType: .audio, outputSettings: audioSettings)
//
//        if reader.canAdd(audioOutput){
//            reader.add(audioOutput)
//        }
//        if writer.canAdd(audioInput){
//            writer.add(audioInput)
//        }
//
//        // Start
//        reader.startReading()
//        writer.startWriting()
//        writer.startSession(atSourceTime: CMTime.zero)
//
//        //创建视频写入队列
//        let videoQueue = DispatchQueue.init(label: "Video Queue")
//        //创建音频写入队列
//        let audioQueue = DispatchQueue.init(label: "Audio Queue")
//        //创建一个线程组
//        let group = DispatchGroup()
//        //进入线程组
//        group.enter()
//
//        //队列准备好后，usingBlock
//        videoInput.requestMediaDataWhenReady(on: videoQueue) {
//
//            var completedOrFailed = false
//            while videoInput.isReadyForMoreMediaData && !completedOrFailed{
//
//                let sampleBuffer = videoOutput.copyNextSampleBuffer()
//                if sampleBuffer != nil{
//                   videoInput.append(sampleBuffer!)
//                }
//                else{
//                    completedOrFailed = true
//                    videoInput.markAsFinished()
//                    group.leave()
//                }
//            }
//        }
//
//        group.enter()
//        audioInput.requestMediaDataWhenReady(on: audioQueue) {
//
//            var completeOrFailed = false
//            while audioInput.isReadyForMoreMediaData && !completeOrFailed{
//
//                let sampleBuffer = audioOutput.copyNextSampleBuffer()
//                if sampleBuffer != nil{
//                    let isSuccess = audioInput.append(sampleBuffer!)
//                    completeOrFailed = !isSuccess
//                }
//                else{
//                    completeOrFailed = true
//                }
//            }
//
//            if completeOrFailed{
//
//                audioInput.markAsFinished()
//                group.leave()
//            }
//        }
//
//        //完成后
//        group.notify(queue: DispatchQueue.main) {
//
//            if reader.status == .reading{
//                reader.cancelReading()
//            }
//
//            switch writer.status{
//            case .writing:
//                fallthrough
//            case .completed:
//                debugPrint("压缩完成")
//                writer.finishWriting {
//                    debugPrint("视频地址:",outputUrl)
//                }
//            case .failed:
//                debugPrint("压缩失败:",writer.error as Any)
//            case .cancelled:
//                debugPrint("取消压缩")
//            case .unknown:
//                break
//            @unknown default:
//                break
//            }
//        }
//    }
//
//    static func configVideoOutput() -> Dictionary<String,Any>?{
//
//        let key1 : String = kCVPixelBufferPixelFormatTypeKey as NSString as String
//
//        return [key1:NSNumber.init(value: kCVPixelFormatType_422YpCbCr8)]
//    }
//
//    static func configAudioOutput() -> Dictionary<String,Any>?{
//
//        return [AVFormatIDKey:NSNumber.init(value: kAudioFormatLinearPCM)]
//    }
//
//
//    static func performanceVideoSettings() -> Dictionary<String,Any>?{
//
//        let compressionProperties : [String:Any] = [AVVideoAverageBitRateKey:NSNumber.init(value: 409600),  // 码率 400K
//                                           AVVideoExpectedSourceFrameRateKey:NSNumber.init(value: 24),      // 帧率
//                                                      AVVideoProfileLevelKey:AVVideoProfileLevelH264HighAutoLevel
//        ]
//
//
//        var videoCodeec : String?
//        if #available(iOS 11.0, *) {
//            videoCodeec = AVVideoCodecType.h264.rawValue
//        } else {
//            videoCodeec = AVVideoCodecH264
//        }
//
//        let videoCompressSettings : [String:Any] = [AVVideoCodecKey:videoCodeec!,
//                                     AVVideoWidthKey:NSNumber.init(value: 640),
//                                    AVVideoHeightKey:NSNumber.init(value: 360),
//                     AVVideoCompressionPropertiesKey:compressionProperties,
//                               AVVideoScalingModeKey:AVVideoScalingModeResizeAspectFill]
//
//        return videoCompressSettings
//    }
//
//    static func performanceAudioSettings() -> Dictionary<String,Any>?{
//
//        var stereoChennelLayout : AudioChannelLayout = AudioChannelLayout.init(mChannelLayoutTag: kAudioChannelLayoutTag_Stereo, mChannelBitmap: AudioChannelBitmap.init(rawValue: 0), mNumberChannelDescriptions: 0, mChannelDescriptions: AudioChannelDescription())
//
//        let channelLayoutAsData = NSData.init(bytes: &stereoChennelLayout, length: MemoryLayout<AudioChannelLayout>.stride)
//
//        let audioCompressSettings = [
//            AVFormatIDKey         : NSNumber.init(value: kAudioFormatMPEG4AAC),
//            AVEncoderBitRateKey   : NSNumber.init(value: 49152), // 码率 48K
//            AVSampleRateKey       : NSNumber.init(value: 44100), // 采样率
//            AVChannelLayoutKey    : channelLayoutAsData,
//            AVNumberOfChannelsKey : NSNumber.init(value: 2)  // 声道
//        ]
//        return audioCompressSettings
//    }
    
    static func buildFilePath() -> String{
        
        let tempPath = FileManager.savePathOfTemp()
        let buildPath = tempPath + "videoCompress/"
        if !FileManager.isExsit(for: buildPath){
            FileManager.createDirectory(at: buildPath)
        }
        return buildPath + "\(Int(Date.timeIntervalSince1970()))" + "_test.mp4"
    }
    
    static func videoQuickCompress(with videoUrl:URL,complete:@escaping ReturnValueBlock<String>){
        
        let asset = AVAsset.init(url: videoUrl)
       
        let session = AVAssetExportSession.init(asset: asset, presetName:AVAssetExportPresetMediumQuality)
        session?.videoComposition = AVVideoComposition.init(propertiesOf: asset)
        
        let path = self.buildFilePath()
        session?.outputURL = URL.init(fileURLWithPath: path)
        
        session?.outputFileType = .mp4
        session?.exportAsynchronously(completionHandler: {
            complete(path)
        })
    }
}
